package cn.han.review;

import org.junit.Test;
import sun.management.snmp.jvminstr.JvmOSImpl;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class TestReflection {
    //1.通过单元测试方法，获取目标类Student对应的字节码对象
    @Test
    public void getClazz() throws ClassNotFoundException {
        Class<?> clazz1 = Class.forName("cn.han.review.Student");
        Class<Student> clazz2 = Student.class;
        Class<? extends Student> clazz3 = new Student().getClass();

        System.out.println(clazz1);
        System.out.println(clazz1.getSimpleName());
        System.out.println(clazz1.getName());
        System.out.println(clazz2.getPackage());//包对象
        System.out.println(clazz2.getPackage().getName());//包对象的属性：包名
    }
    //通过单元测试方法联系引用类型数组的定义与遍历
    @Test
    public  void getStu(){
        Student s1 = new Student("张三",3);
        Student s2 = new Student("李四",4);
        Student s3 = new Student("王五",5);

        Student[] stu = {s1,s2,s3};
        System.out.println(Arrays.toString(stu));
        for (Student s :
                stu) {
            System.out.println(s);
        }


    }
    @Test
    public void getFunction(){
        Class<?> clazz = Student.class;
        Method[] ms = clazz.getMethods();
        for (Method m :
                ms) {
            System.out.println(m);//直接打印遍历到的方法对象
            System.out.println(m.getName());//通过方法对象获取方法名
            Class<?>[] pt = m.getParameterTypes();//通过方法对象获取方法所有参数的数组
            System.out.println(Arrays.toString(pt));//打印方法参数的数组
        }
    }
    //通过单元测试方法，获取Student类中的构造方法
    @Test
    public void getCons(){
        Class<?> clazz = new Student().getClass();
        Constructor<?>[] cs = clazz.getConstructors();
        for (Constructor c :
                cs) {
            System.out.println(c);
            System.out.println(c.getName());
            Class[] pt = c.getParameterTypes();
            System.out.println(Arrays.toString(pt));
        }

    }
    //获取Student类中的成员变量
    @Test
    public void getFie() throws ClassNotFoundException {
        Class<?> clazz = Class.forName("cn.han.review.Student");
        Field[] fs = clazz.getFields();
        /*注意！目前成员变量的修饰符必须是public才能获取到，不然，像默认修饰符也是获取不到的*/
        for (Field f :
                fs) {
            System.out.println(f.getName());//获取字段名
            System.out.println(f.getType());//获取字段的类型
        }
    }
    //通过单元测试方法，创建Student目标类的对象
    @Test
    public void getObject() throws Exception {
        Class<?> clazz = Class.forName("cn.han.review.Student");
        /*反射创建对象方案1：通过触发目标类的无参构造创建对象*/
        Object o = clazz.newInstance();
        System.out.println(o);//获取到Student对象
        /*反射创建对象方案2：通过触发目标类的全参构造创建对象
        * 1.先获取指定的构造函数对象
        * 2.通过刚刚获取到的构造函数对象创建Student目标类的对象，并且给对象的属性赋值*/
        Constructor<?> c = clazz.getConstructor(String.class, int.class);
//        System.out.println(c);
        Object o2 = c.newInstance("赵六", 6);
        System.out.println(o2);
    }

}
